package fr.ul.ade.secunde.ui;

import android.app.Activity;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.BaseColumns;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.actionbarsherlock.app.SherlockListFragment;

import fr.ul.ade.R;
import fr.ul.ade.secunde.database.AdeWebContract;
import fr.ul.ade.secunde.util.UiUtils;

/**
 * Fragment affichant la liste des emplois du temps de l'utilisateur.
 * 
 * @author Michaël Schnell
 * @since Jul 2, 2013
 * 
 * @version 1.6
 */
public class ScheduleListFragment
		extends SherlockListFragment
		implements OnItemLongClickListener, LoaderCallbacks<Cursor>,
		OnClickListener {

	protected ScheduleActionListener scheduleListener;

	protected CursorAdapter listAdapter;

	public static ScheduleListFragment newInstance() {
		return new ScheduleListFragment();
	}

	// --------------------------------------------------------
	//
	// Création et destruction
	//
	// --------------------------------------------------------

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		return UiUtils.getListView(inflater, container);
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		Activity activity = this.getActivity();
		this.scheduleListener = (ScheduleActionListener) activity;

		this.listAdapter = new ScheduleListAdapter(activity);
		this.setListAdapter(this.listAdapter);
		this.getListView().setOnItemLongClickListener(this);

		this.getLoaderManager().initLoader(ScheduleQuery._TOKEN, null, this);
		activity.getContentResolver()
				.registerContentObserver(AdeWebContract.Schedule.CONTENT_URI,
						true,
						this.mScheduleObserver);
	}

	@Override
	public void onDetach() {
		this.getActivity().getContentResolver()
				.unregisterContentObserver(this.mScheduleObserver);
		super.onDetach();
	}

	// --------------------------------------------------------
	//
	// Chargement des données
	//
	// --------------------------------------------------------

	@Override
	public Loader<Cursor> onCreateLoader(int id, Bundle args) {
		Uri scheduleUri = AdeWebContract.Schedule.CONTENT_URI;
		String[] projection = ScheduleQuery.PROJECTION;
		String selection = null;
		String[] selectionArgs = null;

		return new CursorLoader(this.getActivity(), scheduleUri, projection,
				selection, selectionArgs, AdeWebContract.Schedule.DEFAULT_SORT);
	}

	@Override
	public void onLoaderReset(Loader<Cursor> loader) {
		/* Nothing to be done. */
	}

	@Override
	public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
		if (this.getActivity() == null) {
			return;
		}// if
		this.listAdapter.changeCursor(data);
		if (data.getCount() == 0) {
			UiUtils.addEmptyView(this.getActivity().getLayoutInflater(),
					this.getView(),
					this,
					R.string.schedule_list_empty_text);
		}

		final View view = this.getView();
		view.findViewById(R.id.list_loading_progress_bar)
				.setVisibility(View.GONE);
	}

	// --------------------------------------------------------
	//
	// Traitement des évènements
	//
	// --------------------------------------------------------

	@Override
	public void onListItemClick(ListView l, View v, int position, long id) {
		this.scheduleListener.showLessonList(id);
	}

	@SuppressWarnings("resource")
	@Override
	public boolean onItemLongClick(AdapterView<?> parent, View view,
			int position, long id) {
		final Cursor schedule = (Cursor) this.getListAdapter()
				.getItem(position);
		this.scheduleListener.showScheduleDetails(id,
				schedule.getString(ScheduleQuery.SCHEDULE_NAME));
		return true;
	}

	@Override
	public void onClick(View v) {
		this.scheduleListener.showCreateForm();
	}

	private final ContentObserver mScheduleObserver = new ContentObserver(
			new Handler()) {

		@Override
		public void onChange(boolean selfChange) {
			ScheduleListFragment.this.getLoaderManager()
					.restartLoader(ScheduleQuery._TOKEN,
							null,
							ScheduleListFragment.this);
		}

		@Override
		public void onChange(boolean selfChange, Uri uri) {
			this.onChange(selfChange);
		}
	};

	// --------------------------------------------------------
	//
	// Données chargées
	//
	// --------------------------------------------------------

	protected interface ScheduleQuery {
		final int _TOKEN = 0x1;

		final String[] PROJECTION = { BaseColumns._ID,
				AdeWebContract.Schedule.SCHEDULE_NAME,
				AdeWebContract.Schedule.SCHEDULE_DESCRIPTION,
				AdeWebContract.Schedule.SCHEDULE_STATE,
				AdeWebContract.Schedule.SCHEDULE_PERIOD,
				AdeWebContract.Schedule.SCHEDULE_IMPORTANT_CHANGE };

		final int _ID = 0;
		final int SCHEDULE_NAME = 1;
		final int SCHEDULE_DESCRIPTION = 2;
		final int SCHEDULE_STATE = 3;
		final int SCHEDULE_PERIOD = 4;
		final int SCHEDULE_IMPORTANT_CHANGE = 5;
	}

	// --------------------------------------------------------
	//
	// Adaptateur pour la liste
	//
	// --------------------------------------------------------

	protected static class ScheduleListAdapter
			extends CursorAdapter {

		public ScheduleListAdapter(Context context) {
			super(context, null, 0 /* no flags set. */);
		}

		@Override
		public View newView(Context context, Cursor cursor, ViewGroup parent) {
			LayoutInflater inflater = (LayoutInflater) context
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			final View view = inflater.inflate(R.layout.schedule_list_item,
					parent,
					false);
			final ViewHolder holder = new ViewHolder();
			holder.status = (ImageView) view.findViewById(R.id.schedule_status);
			holder.name = (TextView) view.findViewById(R.id.schedule_name);
			holder.description = (TextView) view
					.findViewById(R.id.schedule_description);
			holder.change = (ImageView) view
					.findViewById(R.id.schedule_big_change);
			view.setTag(holder);
			return view;
		}

		@Override
		public void bindView(View view, Context context, Cursor cursor) {
			final ViewHolder holder = (ViewHolder) view.getTag();
			holder.name.setText(cursor.getString(ScheduleQuery.SCHEDULE_NAME));
			holder.description.setText(cursor
					.getString(ScheduleQuery.SCHEDULE_DESCRIPTION));
			holder.status.setImageLevel(cursor
					.getInt(ScheduleQuery.SCHEDULE_STATE));
			boolean hasChange = (cursor
					.getInt(ScheduleQuery.SCHEDULE_IMPORTANT_CHANGE) != 0);
			holder.change.setVisibility(hasChange ? View.VISIBLE : View.GONE);
		}
	}// class ScheduleListAdapter

	/**
	 * Classe auxiliaire utilisée pour accéder aux champs d'un item de la liste.
	 * Stocke les résultats des appels à {@link View#findViewById(int)} afin de
	 * de ne devoir rechercher les champs à chaque mise à jour de la vue.
	 * 
	 * @author Michaël Schnell
	 * @since Jul 6, 2013
	 * 
	 * @version 1.3
	 */
	static class ViewHolder {
		ImageView status;
		TextView name;
		TextView description;
		ImageView change;
	}

}// class ScheduleListFragment